package hasthi.actuators;

import hasthi.common.HasthiException;
import hasthi.common.HasthiException.FaultCode;
import hasthi.config.ResourceProfile;
import hasthi.config.SystemProfileDocument.SystemProfile;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.xml.namespace.QName;

public class SystemBootstrap {
    public static final QName TOMCAT_SERVICE = new QName("http://apache.org","tomcat");
    
    /**
     * To resolve the dependencies, at each step algorithm remove the services who has no dependencies and 
     * remove those services from other's dependencies. (Since they are taken care of). This is continued till dependency map is
     * resolved. To handle before and after dependencies, we convert after dependencies to before dependencies. 
     * e.g. B after A => A before B and use above mentioned algorithm.
     * @param profile
     * @return
     * @throws HasthiException
     */
    public List<QName> createOrderedServiceList(SystemProfile profile) throws HasthiException{
        Map<QName,List<QName>> dependenacyMap = new HashMap<QName, List<QName>>();
        List<QName> orderedServiceList = new ArrayList<QName>();
        
        for(ResourceProfile resourceConfig:profile.getResourceArray()){
            ArrayList<QName> list = new ArrayList<QName>();
            if(resourceConfig.getBehaviour().getDependancyArray() != null){
                Collections.addAll(list, resourceConfig.getBehaviour().getDependancyArray());    
            }
            dependenacyMap.put(resourceConfig.getName(), list );
        }
        
        List<QName> toAdded = new ArrayList<QName>();
        while(dependenacyMap.size() == 0){
            //remove emprty lists
            for(QName name:dependenacyMap.keySet()){
                if(dependenacyMap.get(name).size() == 0){
                    toAdded.add(name);
                }
            }
            for(QName name:toAdded){
                dependenacyMap.remove(name);
            }
            
            orderedServiceList.addAll(toAdded);
            for(List<QName> list:dependenacyMap.values()){
                list.removeAll(toAdded);
            }
            if(toAdded.size() == 0){
                throw new HasthiException("Can not resolve depandancies of "+ dependenacyMap, FaultCode.InitalizationError);
            }
            toAdded.clear();
        }
        return orderedServiceList;
    }
    
    public void deploy(ActionCenter managerRing) throws HasthiException{
        List<QName> orderedServiceList = createOrderedServiceList(managerRing.getActionContext().getSystemConfig().getProfile());
        
        for(QName serviceName:orderedServiceList){
            managerRing.createService(serviceName.toString());
        }
        
        managerRing.planAndExecuate();
        
    }
    
    
    
    
}
